package com.jingtai.shop.service.goods.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.jingtai.common.annotation.TransactionalWithRollback;
import com.jingtai.common.constants.RedisConstant;
import com.jingtai.common.enums.*;
import com.jingtai.common.utils.MyBeanUtils;
import com.jingtai.common.utils.random.TokenUtil;
import com.jingtai.core.entity.merchants.MerchantsToMemberOrder;
import com.jingtai.core.entity.merchants.MerchantsToMemberOrderDetail;
import com.jingtai.core.entity.shop.MerchantsGoods;
import com.jingtai.core.entity.shop.MerchantsGoodsWarehouse;
import com.jingtai.core.mapper.merchants.MerchantsInfoMapper;
import com.jingtai.core.webfacade.dto.UserShopCartDTO;
import com.jingtai.shop.service.goods.MerchantsGoodsService;
import com.jingtai.shop.service.goods.MerchantsGoodsWarehouseService;
import com.jingtai.shop.service.goods.ShopCartService;
import com.jingtai.shop.service.order.MerchantsToMemberOrderDetailService;
import com.jingtai.shop.service.order.MerchantsToMemberOrderService;
import com.jingtai.shop.webfacade.bo.shopcar.ModifyShopCarQuantityBO;
import com.jingtai.shop.webfacade.bo.shopcar.ShopCarRemoveBO;
import com.jingtai.shop.webfacade.bo.shopcar.SubmitOrderDetailBO;
import com.jingtai.shop.webfacade.bo.shopcar.SubmitOrderTotalBO;
import com.jingtai.shop.webfacade.vo.shopcar.list.ListShopCartVO;
import com.jingtai.shop.webfacade.vo.shopcar.list.ShopCartVO;
import com.jingtai.shop.webfacade.vo.shopcar.list.TotalShopCarVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ShopCartServiceImpl implements ShopCartService {

    @Resource
    private RedisTemplate<String, String> redisTemplate;
    @Resource
    private MerchantsInfoMapper merchantsInfoMapper;
    @Resource
    private MerchantsToMemberOrderService orderService;
    @Resource
    private MerchantsToMemberOrderDetailService orderDetailService;
    @Resource
    private MerchantsGoodsService goodsService;
    @Resource
    private MerchantsGoodsWarehouseService goodsWarehouseService;


    private static final String CONNECT = "&";

    /**
     * 添加购物车
     *
     * @param goodsId  商品id
     * @param skuCode  sku编码(属性编码)
     * @param quantity 数量
     * @param userId   用户id
     */
    @Override
    public void saveShopCart(Long goodsId, String skuCode, Long quantity, Long userId) {
        String shopCarKey = RedisConstant.SHOP_CAR_PRE_KEY + userId;
        // 保存到购物车，key商品的id + & + skuCode，value商品数量
        String hashKey = goodsId + CONNECT + skuCode;
        // 判断是否有相同商品，规格的物品，有数量加1
        if (redisTemplate.opsForHash().hasKey(shopCarKey, hashKey)) {
            redisTemplate.opsForHash().increment(shopCarKey, hashKey, quantity);
        } else {
            redisTemplate.opsForHash().put(shopCarKey, hashKey, quantity);
        }
    }

    /**
     * 清空购物车
     *
     * @param userId 用户id
     */
    @Override
    public void clearShopCart(Long userId) {
        String shopCarKey = RedisConstant.SHOP_CAR_PRE_KEY + userId;
        redisTemplate.delete(shopCarKey);
    }

    /**
     * 删除购物车商品
     */
    @Override
    public void removeShopCart(ShopCarRemoveBO bo, Long userId) {
        String shopCarKey = RedisConstant.SHOP_CAR_PRE_KEY + userId;
        bo.getIdAndSkuList().forEach(vo -> {
            String hashKey = vo.getGoodsId() + CONNECT + vo.getSkuCode();
            redisTemplate.opsForHash().delete(shopCarKey, hashKey);
        });
    }

    /**
     * 用户购物车列表
     */
    @Override
    public List<TotalShopCarVO> listUserShopCart(Long userId) {
        String shopCarKey = RedisConstant.SHOP_CAR_PRE_KEY + userId;
        //获取key下的键值对
        Map<Object, Object> map = redisTemplate.opsForHash().entries(shopCarKey);
        List<ListShopCartVO> shopCarListVOS = new ArrayList<>();
        map.forEach((key, value) -> {
            //获取key值
            String hashKey = (String) key;
            //获取value值
            String[] split = hashKey.split(CONNECT);

            UserShopCartDTO shopCartDTO = merchantsInfoMapper.selectShopCartList(split[0], split[1]);
            ListShopCartVO ShopCartVO = MyBeanUtils.copyPropertiesChaining(shopCartDTO, ListShopCartVO::new);
            ShopCartVO.setQuantity((Integer) value);
            shopCarListVOS.add(ShopCartVO);
        });
        //根据店铺主键id去重,转换到总购物车列表中
        List<TotalShopCarVO> totalShopCarVOS = shopCarListVOS.stream().collect(
                Collectors.collectingAndThen(Collectors.toCollection(
                        () -> new TreeSet<>(Comparator.comparing(o -> o.getStoreId()))), ArrayList::new))
                .stream().map(shopCartVO -> MyBeanUtils.copyPropertiesChaining(shopCartVO, TotalShopCarVO::new))
                .collect(Collectors.toList());
        //根据店铺id过滤判断,是此店铺的商品插入进去
        totalShopCarVOS.forEach(shop -> shop.setShopCartVOS(
                shopCarListVOS.stream().filter(listShop -> ObjectUtil.equal(shop.getStoreId(), listShop.getStoreId()))
                        .map(shopCart ->
                                MyBeanUtils.copyPropertiesChaining(shopCart, ShopCartVO::new)
                        ).collect(Collectors.toList())
        ));
        return totalShopCarVOS;
    }

    /**
     * 修改购物车商品信息
     */
    @Override
    public void updateShopCart(ModifyShopCarQuantityBO bo, Long userId) {
        String shopCarKey = RedisConstant.SHOP_CAR_PRE_KEY + userId;

        if (!Objects.equals(bo.getSkuCode(), bo.getOldSkuCode())) {
            String oldHashKey = bo.getGoodsId() + CONNECT + bo.getOldSkuCode();
            redisTemplate.opsForHash().delete(shopCarKey, oldHashKey);
        }

        String hashKey = bo.getGoodsId() + CONNECT + bo.getSkuCode();
        redisTemplate.opsForHash().put(shopCarKey, hashKey, bo.getQuantity());
    }

    /**
     * 选择购物车商品,跳转到预提交订单页面->预提交订单
     */
    @Override
    public Map<String, Object> preCommitOrder(Long userId, List<String> skuCode) {
        return null;
    }

    /**
     * 购物车提交订单
     */
    @TransactionalWithRollback
    @Override
    public boolean submitOrder(SubmitOrderTotalBO bo, Long userId) {
        String orderTotalNo = TokenUtil.generateOrderNo();
        MerchantsToMemberOrder memberOrder = new MerchantsToMemberOrder();
        memberOrder.setMerchantsId(bo.getMerchantsId());
        memberOrder.setMemberId(userId);
        memberOrder.setMemberAddressId(bo.getMemberAddressId());
        memberOrder.setOrderTotalCode(orderTotalNo);
        memberOrder.setGoodsTotalPrice(bo.getGoodsTotalPrice());
        memberOrder.setFreight(bo.getTotalFreight());
        memberOrder.setPreferentialPrice(bo.getPreferentialTotalPrice());
        memberOrder.setMemberRealPay(bo.getMemberRealTotalPay());
        memberOrder.setPayState(PayStatusEnum.UNPAID.getStatus());
        memberOrder.setOrderState(OrderStatusEnum.WAIT_PAY.getStatus());
        boolean saveOrderStatus = orderService.save(memberOrder);
        log.info("添加总订单状态:{}", saveOrderStatus);

        List<SubmitOrderDetailBO> orderDetailBOList = bo.getOrderDetailsBOS();
        //获取sku编码
        List<String> skuCodeList = orderDetailBOList.stream().map(order -> order.getSkuCode()).collect(Collectors.toList());
        //获取商品编码
        List<String> goodsCodeList = orderDetailBOList.stream().map(order -> order.getGoodsCode()).collect(Collectors.toList());
        //查询传入进来的sku编码
        List<MerchantsGoodsWarehouse> warehouseList = goodsWarehouseService.list(Wrappers.lambdaQuery(MerchantsGoodsWarehouse.class)
                .in(MerchantsGoodsWarehouse::getSkuCode, skuCodeList));
        //查询传入的商品编码
        List<MerchantsGoods> goodsList = goodsService.list(Wrappers.lambdaQuery(MerchantsGoods.class).in(MerchantsGoods::getGoodsCode, goodsCodeList));

        //插入传入进来的参数
        List<MerchantsToMemberOrderDetail> orderDetailList = orderDetailBOList.stream().map(orderDetails -> {
            MerchantsToMemberOrderDetail orderDetail = MyBeanUtils.copyPropertiesChaining(orderDetails, MerchantsToMemberOrderDetail::new);
            orderDetail.setOrderTotalCode(orderTotalNo);
            orderDetail.setOrderChildCode(TokenUtil.generateOrderNo());
            orderDetail.setGoodsRefundState(OrderRefundStatusEnum.NO_REFUND.getStatus());
            orderDetail.setInventoryBackState(InventoryReturnStatusEnum.NO_ROLLBACK.getStatus());
            return orderDetail;
        }).collect(Collectors.toList());

        //根据sku编码对比,插入商品属性的部分信息
        orderDetailList.stream().
                forEach(orderDetails -> {
                    warehouseList.stream().filter(warehouse -> StringUtils.equals(warehouse.getSkuCode(), orderDetails.getSkuCode()))
                            .forEach(warehouse -> {
                                orderDetails.setMerchantsId(warehouse.getMerchantsId());
                                orderDetails.setSupplyPrice(warehouse.getCostPrice());
                                orderDetails.setGoodsJson(warehouse.getSpecificationsJson());
                            });
                });
        //根据goods编码对比,插入商品剩余信息
        orderDetailList.stream().
                forEach(orderDetails->{
                    goodsList.stream().filter(goods->StringUtils.equals(goods.getGoodsCode(),orderDetails.getGoodsCode()))
                            .forEach(goods->{
                                orderDetails.setGoodsSource(goods.getGoodsSource());
                                orderDetails.setGoodsName(goods.getGoodsListTitle());
                                orderDetails.setGoodsImages(goods.getMainFigure());
                                orderDetails.setGoodsUnitPrice(goods.getGoodsPrice());
                            });
                });
        boolean saveBatchStatus = orderDetailService.saveBatch(orderDetailList);
        log.info("添加子订单状态:{}", saveOrderStatus);
        return saveBatchStatus;
    }

    @Override
    public List<TotalShopCarVO> selectGoodsBySkuCode(String skuCode,String type,Long goodsId,Integer quantity, Long userId) {
        List<ListShopCartVO> shopCarListVOS = new ArrayList<>();
        if(type.equals("1")){
            String shopCarKey = RedisConstant.SHOP_CAR_PRE_KEY + userId;
            //获取key下的键值对
            Map<Object, Object> map = redisTemplate.opsForHash().entries(shopCarKey);
            map.forEach((key, value) -> {
                //获取key值
                String hashKey = (String) key;
                //获取value值
                String[] split = hashKey.split(CONNECT);

                UserShopCartDTO shopCartDTO = merchantsInfoMapper.selectShopCartList(split[0], split[1]);
                ListShopCartVO ShopCartVO = MyBeanUtils.copyPropertiesChaining(shopCartDTO, ListShopCartVO::new);
                ShopCartVO.setQuantity((Integer) value);
                if(Arrays.asList(skuCode.split(",")).contains(ShopCartVO.getSkuCode())){
                    shopCarListVOS.add(ShopCartVO);
                }
            });
        }else {
            //根据skuCode 查询goodsId
            UserShopCartDTO shopCartDTO = merchantsInfoMapper.selectShopCartList(goodsId.toString(), skuCode);
            ListShopCartVO ShopCartVO = MyBeanUtils.copyPropertiesChaining(shopCartDTO, ListShopCartVO::new);
            ShopCartVO.setQuantity(quantity);
            if(Arrays.asList(skuCode.split(",")).contains(ShopCartVO.getSkuCode())){
                shopCarListVOS.add(ShopCartVO);
            }
        }


        //根据店铺主键id去重,转换到总购物车列表中
        List<TotalShopCarVO> totalShopCarVOS = shopCarListVOS.stream().collect(
                Collectors.collectingAndThen(Collectors.toCollection(
                        () -> new TreeSet<>(Comparator.comparing(o -> o.getStoreId()))), ArrayList::new))
                .stream().map(shopCartVO -> MyBeanUtils.copyPropertiesChaining(shopCartVO, TotalShopCarVO::new))
                .collect(Collectors.toList());
        //根据店铺id过滤判断,是此店铺的商品插入进去
        totalShopCarVOS.forEach(shop -> shop.setShopCartVOS(
                shopCarListVOS.stream().filter(listShop -> ObjectUtil.equal(shop.getStoreId(), listShop.getStoreId()))
                        .map(shopCart ->
                                MyBeanUtils.copyPropertiesChaining(shopCart, ShopCartVO::new)
                        ).collect(Collectors.toList())
        ));
        return totalShopCarVOS;
    }
}
